package com.horzion.httpclient;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.horzion.httpclient.entity.User;
import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.*;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.InputStreamEntity;
import org.apache.http.entity.StringEntity;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.junit.Test;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.InputStream;
import java.net.URI;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;


public class Demo01 {


    @Test
    public void test1() throws Exception {

        // 获取HttpClient实例
        CloseableHttpClient httpClient = HttpClients.createDefault();

        // 创建一个HttpGet请求
        HttpGet httpGet = new HttpGet("http://localhost:8080/user");

        // 发送请求,获取响应结果
        CloseableHttpResponse response = httpClient.execute(httpGet);

        // 获取响应实体
        HttpEntity responseEntity = response.getEntity();

        System.out.println("响应状态: " + response.getStatusLine());
        if (responseEntity != null) {
            System.out.println("响应内容长度为:" + responseEntity.getContentLength());
            System.out.println("响应内容为:" + EntityUtils.toString(responseEntity));
        }
    }

    @Test
    public void test2() throws Exception {
        // 获取HttpClient实例
        CloseableHttpClient httpClient = HttpClients.createDefault();

        // 请求参数
        StringBuilder params = new StringBuilder();
        params.append("?");
        // 字符数据最好encoding一下;这样一来，某些特殊字符才能传过去(如:username就是"&",不encoding的话,解析时,会认为要拼接下一个参数username就为空)
        params.append("username=" + URLEncoder.encode("admin", "UTF8"));

        HttpGet httpGet = new HttpGet("http://localhost:8080/user/testGet" + params);

        // 发送请求,获取响应结果
        CloseableHttpResponse response = httpClient.execute(httpGet);

        // 获取响应实体
        HttpEntity responseEntity = response.getEntity();

        System.out.println("响应状态: " + response.getStatusLine());
        if (responseEntity != null) {
            System.out.println("响应内容长度为:" + responseEntity.getContentLength());
            System.out.println("响应内容为:" + EntityUtils.toString(responseEntity));
        }

    }

    // GET请求(使用URI获取HttpGet)
    @Test
    public void test3() throws Exception {
        // 获取HttpClient实例
        CloseableHttpClient httpClient = HttpClients.createDefault();

        // 将参数放入键值对类NameValuePair中,再放入集合中
        List<NameValuePair> params = new ArrayList<>();
        params.add(new BasicNameValuePair("username", "admin"));

        // 设置uri信息,并将参数集合放入uri;
        // 注:这里也支持一个键值对一个键值对地往里面放setParameter(String key, String value)
        URI uri = new URIBuilder().setScheme("http").setHost("localhost")
                .setPort(8080).setPath("/user/testGet")
                .setParameters(params).build();

        HttpGet httpGet = new HttpGet(uri);

        print(httpClient, httpGet);
    }


    @Test
    public void test4() throws Exception {
        // 获取HttpClient实例
        CloseableHttpClient httpClient = HttpClients.createDefault();

        HttpPost httpPost = new HttpPost("http://localhost:8080/user/testPost");

        print(httpClient, httpPost);

    }

    @Test
    public void test5() throws Exception {
        // 获取HttpClient实例
        CloseableHttpClient httpClient = HttpClients.createDefault();

        HttpPost httpPost = new HttpPost("http://localhost:8080/user/testPost?username=admin");

        print(httpClient, httpPost);

    }

    // POST请求(带有对象)
    @Test
    public void test6() throws Exception {
        // 获取HttpClient实例
        CloseableHttpClient httpClient = HttpClients.createDefault();

        User user = new User();
        user.setUsername("王五");

        // json转换工具
        ObjectMapper om = new ObjectMapper();
        StringEntity entity = new StringEntity(om.writeValueAsString(user), "utf-8");

        HttpPost httpPost = new HttpPost("http://localhost:8080/user");

        // post请求是将参数放在请求体里面传过去的;这里将entity放入post请求体中
        httpPost.setEntity(entity);

        // 设置请求头
        httpPost.setHeader("Content-Type", "application/json;charset=utf8");
        httpClient.execute(httpPost);

        print(httpClient, httpPost);

    }

    @Test
    public void test7() throws Exception {
        // 获取HttpClient实例
        CloseableHttpClient httpClient = HttpClients.createDefault();

        User user = new User();
        user.setUsername("赵六");

        // json转换工具
        ObjectMapper om = new ObjectMapper();
        StringEntity entity = new StringEntity(om.writeValueAsString(user), "utf-8");

        // 构建uri
        URI uri = new URIBuilder().setScheme("http").setHost("localhost")
                .setPort(8080).setPath("/user/testPost3")
                .setParameter("flag", "测试post请求带参哦！")       //使用setParameter设置单个参数
                .build();

        HttpPost httpPost = new HttpPost(uri);

        // post请求是将参数放在请求体里面传过去的;这里将entity放入post请求体中
        httpPost.setEntity(entity);

        // 设置请求头
        httpPost.setHeader("Content-Type", "application/json;charset=utf8");
        httpClient.execute(httpPost);

        print(httpClient, httpPost);

    }


    // PUT方式发送请求
    @Test
    public void test8() throws Exception {
        // 获取HttpClient实例
        CloseableHttpClient httpClient = HttpClients.createDefault();


        User user = new User();
        user.setUsername("管理员");


        ObjectMapper om = new ObjectMapper();
        String userStr = om.writeValueAsString(user);
        // 构建实体
        StringEntity entity = new StringEntity(userStr, StandardCharsets.UTF_8);

        HttpPut httpPut = new HttpPut("http://localhost:8080/user/12");

        // 设置请求头
        httpPut.setHeader("Content-Type", "application/json;charset=utf8");
        httpPut.setEntity(entity);

        httpClient.execute(httpPut);

        print(httpClient, httpPut);
    }


    // DELETE   方式发送请求
    @Test
    public void test9() throws Exception {
        // 获取HttpClient实例
        CloseableHttpClient httpClient = HttpClients.createDefault();

        HttpDelete httpDelete = new HttpDelete("http://localhost:8080/user/8");

        httpClient.execute(httpDelete);

        print(httpClient, httpDelete);

    }


    // application/x-www-form-urlencoded 类型表单请求实例
    @Test
    public void test10() throws Exception {
        // 获取HttpClient实例
        CloseableHttpClient httpClient = HttpClients.createDefault();

        HttpPost httpPost = new HttpPost("http://localhost:8080/user/testForm");

        // 设置请求头
        httpPost.setHeader("Content-Type", "application/x-www-form-urlencoded");

        List<BasicNameValuePair> params = new ArrayList<>();
        params.add(new BasicNameValuePair("id", "100"));
        params.add(new BasicNameValuePair("username", "张三"));
        // 这里不要传递birthday,后台需要定义converter,做类型转换(String->Date),你们有兴趣自己去玩
//        params.add(new BasicNameValuePair("birthday",new SimpleDateFormat("yyyy-MM-dd").format(new Date())));
        params.add(new BasicNameValuePair("pic", "https://www.baidu.com/favicon.ico"));

        // 构建一个虚拟表单,并设置参数
        UrlEncodedFormEntity entity = new UrlEncodedFormEntity(params, StandardCharsets.UTF_8);

        // 设置请求实体
        httpPost.setEntity(entity);

        // 发送请求
        httpClient.execute(httpPost);

        print(httpClient, httpPost);

    }


    @Test
    public void test11() throws Exception {
        // 获取HttpClient实例
        CloseableHttpClient httpClient = HttpClients.createDefault();

        MultipartEntityBuilder multipartEntityBuilder = MultipartEntityBuilder.create();

        // 可以添加多个图片(name保持一致就行,后台使用List<MultipartFile> pic接收)
//        multipartEntityBuilder.addBinaryBody("pic",new File("D:\\10.png"));
        multipartEntityBuilder.addBinaryBody("pic", new File("D:\\11.png"));

        // 携带文本参数
        multipartEntityBuilder.addTextBody("username", "管理员", ContentType.create("text/plain", StandardCharsets.UTF_8));

        // 装换为HttpEntity
        HttpEntity entity = multipartEntityBuilder.build();

        HttpPost httpPost = new HttpPost("http://localhost:8080/user/upload");

        httpPost.setEntity(entity);

        print(httpClient, httpPost);

    }


    // 发送数据流
    @Test
    public void test12() throws Exception {
        // 获取HttpClient实例
        CloseableHttpClient httpClient = HttpClients.createDefault();

        InputStream is = new ByteArrayInputStream("admin".getBytes());

        // 构建数据流实体
        InputStreamEntity entity = new InputStreamEntity(is);

        HttpPost httpPost = new HttpPost("http://localhost:8080/user/testStream");

        httpPost.setEntity(entity);

        // 发送请求
        httpClient.execute(httpPost);

        print(httpClient, httpPost);

    }

    /**
     * 抽取打印方法
     *
     * @param httpClient
     * @param http
     * @throws Exception
     */
    private void print(CloseableHttpClient httpClient, HttpRequestBase http) throws Exception {
        // 发送请求,获取响应结果
        CloseableHttpResponse response = httpClient.execute(http);

        // 获取响应实体
        HttpEntity responseEntity = response.getEntity();

        System.out.println("响应状态: " + response.getStatusLine());
        if (responseEntity != null) {
            System.out.println("响应内容长度为:" + responseEntity.getContentLength());

            System.out.println("响应内容为:" + EntityUtils.toString(responseEntity, "UTF8"));
        }

        response.close();
        httpClient.close();
    }
}
